﻿using System;
using System.IO;
using System.Reflection;
using System.Collections.Generic;
using OrganizationName.CodeGeneration;
using OrganizationName.Runtime;

namespace OrganizationName.Factory
{
    public class Type : GenericMaterial
    {
        public override System.CodeDom.CodeExpression ToRightHandSideExpression(ICodeContext codeContext)
        {
            throw new NotImplementedException();
        }

        public override void DeclarationPhase(ICodeContext codeContext)
        {
            throw new NotImplementedException();
        }

        public override void InitializationPhase(ICodeContext codeContext)
        {
            throw new NotImplementedException();
        }

        public override void FinalizationPhase(ICodeContext codeContext)
        {
            throw new NotImplementedException();
        }

        public override System.Type GetAbstractType(ICodeContext codeContext)
        {
            throw new NotImplementedException();
        }

        public override System.Type GetConcreteType(ICodeContext codeContext)
        {
            if (string.IsNullOrEmpty(Impl))
            {
                throw new CodeGenerationException("Concrete type could not be determined because \"Impl\" attribute is null or empty", codeContext, null);
            }

            string implKey = Impl.ToLowerInvariant();

            if (!codeContext.DynamicallyLoadedTypes.ContainsKey(implKey))
            {
                lock (codeContext.DynamicallyLoadedTypes)
                {
                    if (!codeContext.DynamicallyLoadedTypes.ContainsKey(implKey))
                    {
                        try
                        {
                            codeContext.DynamicallyLoadedTypes.Add(implKey, Loader.Instance.LoadType(Impl).Type);
                        }
                        catch (Exception typeLoadException)
                        {
                            throw new CodeGenerationException("Concrete type could not be loaded. Impl=\"" + Impl + "\"", codeContext, typeLoadException);
                        }
                    }
                }
            }
            return codeContext.DynamicallyLoadedTypes[implKey];
        }
    }
}
